package com.db.priceApp.domain.clientDataBasa;

import java.nio.channels.SelectionKey;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.Logger;

public class ClientsBasa {
	
	private final ConcurrentHashMap<String,ClientProfile> clients;
	private final ConcurrentHashMap<SelectionKey, String> connections;
	private final BlockingQueue<ClientProfile> subscribers;
	private Logger logger = Logger.getLogger(ClientsBasa.class.getName());

	public ClientsBasa(ConcurrentHashMap<String, ClientProfile> clients) {
		
		this.clients = clients;
		connections = new ConcurrentHashMap<SelectionKey, String>();
		subscribers = new LinkedBlockingQueue<ClientProfile>(clients.values());
	}	
	
	public int getNumOfClients (){
		return clients.size();
	}
	
	public ClientProfile getNextSubscriber() throws InterruptedException{
		return subscribers.take();
	}
	
	public boolean putSubscriber(ClientProfile client){
		return subscribers.add(client);
	}
	
	public String getLogin(SelectionKey key){
		return connections.get(key);
	}
	
	public ClientProfile getClient (String login){
		return clients.get(login);
	}

	public boolean containsClient (ClientProfile client) {
		String login = client.getLogin();
		if (login == null){
			logger.warning("login is empty");
			return false;
		}
		return clients.containsKey(login);
	}
	
	public boolean containsClient (String login) {
		if (login == null){
			logger.warning("login is empty2");
			return false;
		}
		return clients.containsKey(login);
	}
	
	public boolean containsClient (SelectionKey key) {
		String login = connections.get(key);
		if (login == null){
			logger.info("new client");
			return false;
		}
		return clients.containsKey(login);
	}

	public void addClient(ClientProfile client) throws IllegalArgumentException{
		String login = client.getLogin();
		SelectionKey key = client.getSelectionKey();
		if (key == null){
			logger.warning("there is no connection with the client");
			throw new IllegalArgumentException("there is no connection with the client");
		}
		if (login == null || login.equals("")) {
			logger.warning("illegal value of a login");
			throw new IllegalArgumentException("illegal value of a login");
		}
		
		
		if(clients.putIfAbsent(client.getLogin(), client) != null ||
				connections.putIfAbsent(key, login) != null) {
			logger.warning("login " + login + " is already taken");
			throw new IllegalArgumentException("login " + login + " is already taken");
		}
		subscribers.add(client);
	}
	
	public void removeClient (String login) throws IllegalArgumentException {
		ClientProfile client = clients.get(login);
		if (client == null) {
			logger.warning("there is no client " + login);
			throw new IllegalArgumentException("there is no client " + login);
		}
		SelectionKey key = client.getSelectionKey();
		clients.remove(login);
		connections.remove(key);
		subscribers.remove(client);
	}
	
	public void removeClient (SelectionKey key) throws IllegalArgumentException {
		if(key == null) {
			logger.warning("connection is already removed");
			return;
		}
		String login = connections.get(key);
		if (login == null) {
			logger.warning("there is no client with such SelectionKey");
			throw new IllegalArgumentException("there is no client with such SelectionKey");
		}
		connections.remove(key);
		if(clients.remove(login) == null) {
			logger.warning("there is no client " + login);
			throw new IllegalArgumentException("there is no client " + login);
		}
	}

	public void clear() {
		clients.clear();
		connections.clear();
		subscribers.clear();
	}
}
